package zero.tech.games.extension.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import zero.tech.games.common.RedisConsts;
import zero.tech.games.common.topic.ProxyAdd;
import zero.tech.redis.cache.RedisUtil;

@Component
public class ExtensionUtil {
	private static final Map<Integer,Map<Integer,Integer>> club_proxy_tree=new HashMap<Integer, Map<Integer,Integer>>();
	@Autowired
	private RedisUtil redisUtil;
	public static void main(String[] args) {
		ExtensionUtil extensionUtil= new ExtensionUtil();
		List<ProxyAdd> list=new ArrayList<>();
		list.add(new ProxyAdd(1,1,2));
		list.add(new ProxyAdd(2,10,1));
		list.add(new ProxyAdd(1,2,3));
		list.add(new ProxyAdd(1,3,4));
		list.add(new ProxyAdd(1,4,5));
		list.add(new ProxyAdd(1,5,2));
		list.add(new ProxyAdd(1,6,3));
		list.add(new ProxyAdd(1,7,6));
		list.add(new ProxyAdd(1,8,6));
		list.add(new ProxyAdd(1,9,3));
		list.add(new ProxyAdd(1,11,9));
		extensionUtil.toBeTree(list);
		System.out.println(club_proxy_tree);
		System.out.println(extensionUtil.getZsSubIds(1, 3));
		System.out.println(extensionUtil.getFzsSubIds(1, 3));
		System.out.println(extensionUtil.getAllSubIds(1, 3));
		System.out.println(extensionUtil.getParentIds(1, 3));
	}
	
	
	@SuppressWarnings("unchecked")
	public List<Integer> getZsSubIds(int club_id,int uid) {
		List<Integer> zs=(List<Integer>) redisUtil.hget(RedisConsts.HOT_EXTENSION+"_"+club_id,String.valueOf(uid)+"_ZSSUBIDS");
		if(zs==null) {
			zs=new ArrayList<>();
			zsDigui(zs,club_id,uid);
			redisUtil.hset(RedisConsts.HOT_EXTENSION+"_"+club_id,String.valueOf(uid)+"_ZSSUBIDS", zs,5*60);
		}
		return zs;
	}


	@SuppressWarnings("unchecked")
	public List<Integer> getFzsSubIds(int club_id,int uid) {
		List<Integer> childs=(List<Integer>) redisUtil.hget(RedisConsts.HOT_EXTENSION+"_"+club_id,String.valueOf(uid)+"_FZSSUBIDS");
		if(childs==null) {
			childs=new ArrayList<>();
			List<Integer> zs=getZsSubIds(club_id, uid);
			for(Integer zs_uid:zs) {
				childDigui(childs, club_id, zs_uid);
			}
			redisUtil.hset(RedisConsts.HOT_EXTENSION+"_"+club_id,String.valueOf(uid)+"_FZSSUBIDS", childs,5*60);
		}
		return childs;
	}
	
	@SuppressWarnings("unchecked")
	public List<Integer> getAllSubIds(int club_id,int uid) {
		List<Integer> allsubs=(List<Integer>) redisUtil.hget(RedisConsts.HOT_EXTENSION+"_"+club_id,String.valueOf(uid)+"_ALLSUBIDS");
		if(allsubs==null) {
			allsubs=new ArrayList<>();
			List<Integer> zs=getZsSubIds(club_id, uid);
			allsubs.addAll(zs);
			List<Integer> childs=new ArrayList<>();
			for(Integer zs_uid:zs) {
				childDigui(childs, club_id, zs_uid);
			}
			allsubs.addAll(childs);
			redisUtil.hset(RedisConsts.HOT_EXTENSION+"_"+club_id,String.valueOf(uid)+"_ALLSUBIDS", allsubs,5*60);
		}
		return allsubs;
	}
	
	
	public List<Integer> getParentIds(int club_id, int uid) {
		List<Integer> list =new ArrayList<>();
		Map<Integer,Integer> proxy_map=club_proxy_tree.get(club_id);
		if(proxy_map==null) {
			proxy_map=new HashMap<>();
		}
		list.addAll(getParentIdsByRelation(uid, proxy_map));
		return list;
	}
	
	
	private void zsDigui(List<Integer> zs,int club_id, int uid) {
		Map<Integer,Integer> proxy_map=club_proxy_tree.get(club_id);
		if(proxy_map!=null) {
			for (Entry<Integer, Integer> entry : proxy_map.entrySet()) {
				Integer father_uid = entry.getValue();
				if (father_uid==uid) {
					int child_uid=entry.getKey();
					if(!zs.contains(child_uid)) {
						zs.add(entry.getKey());
					}
				}
			}		
		}
	}
	
	private void childDigui(List<Integer> childs, int club_id, int uid) {
		Map<Integer,Integer> proxy_map=club_proxy_tree.get(club_id);
		if(proxy_map!=null) {
			for (Entry<Integer, Integer> entry : proxy_map.entrySet()) {
				int father_uid = entry.getValue();
				if(father_uid==uid) {
					int child_uid=entry.getKey();
					if(!childs.contains(child_uid)) {
						childs.add(child_uid);
					}
					childDigui(childs, club_id, child_uid);
				}
			}		
		}
	}
	
	private boolean checkXunhuantree(int uid, int father_uid, Map<Integer, Integer> proxy_map) {
		List<Integer> list = getParentIdsByRelation(father_uid,proxy_map);
		return list.contains(uid);
	}
	
	private List<Integer> getParentIdsByRelation(int uid, Map<Integer, Integer> proxy_map) {
		List<Integer> list =new ArrayList<>();
		diguiFindParents(list,uid,proxy_map);
		return list;
	}
	private void diguiFindParents(List<Integer> list, int uid, Map<Integer, Integer> proxy_map) {
		if (proxy_map.containsKey(uid)) {
			Integer father_uid = proxy_map.get(uid);
			if (father_uid != null&&father_uid!=uid) {
				list.add(father_uid);
				diguiFindParents(list, father_uid,proxy_map);
			}
		}
	}
	
	//形成内存树(且去除循环引用关系)
	public void toBeTree(List<ProxyAdd> proxyAdds) {
		Map<Integer,Map<Integer,Integer>> tmp_tree=new HashMap<Integer, Map<Integer,Integer>>();
		for(ProxyAdd clubProxy:proxyAdds) {
			int club_id=clubProxy.getClub_id();
			int uid=clubProxy.getUid();
			Integer father_uid=clubProxy.getFather_uid();
			if(!tmp_tree.containsKey(club_id)) {
				Map<Integer,Integer>map=new HashMap<>();
				map.put(uid, father_uid);
				tmp_tree.put(club_id, map);
			}else {
				Map<Integer,Integer>map=tmp_tree.get(club_id);
				map.put(uid, father_uid);
			}
		}
		for(Entry<Integer,Map<Integer,Integer>> entry:tmp_tree.entrySet()) {
			Integer club_id=entry.getKey();
			Map<Integer,Integer> map=entry.getValue();
			for(Integer uid:map.keySet()) {
				tree(club_id,uid,map);
			}
		}		
	}

	private void tree(int club_id,int uid, Map<Integer, Integer> relation) {
		Map<Integer,Integer> proxy_map=club_proxy_tree.get(club_id);
		if(proxy_map==null) {
			proxy_map=new HashMap<>();
			club_proxy_tree.put(club_id, proxy_map);
		}
		if (!proxy_map.containsKey(uid)) {
			Integer father_uid = relation.get(uid);
			if (father_uid != null && father_uid != uid) {
				if (!checkXunhuantree(uid, father_uid,proxy_map)) {
					proxy_map.put(uid, father_uid);
					tree(club_id,father_uid, relation);
				}
			}
		}
	}


	public void proxyAddDynamic(int club_id, int uid, int father_uid) {
		System.out.println("俱乐部:"+club_id+",用户:"+uid+"绑定上级为:"+father_uid);
		Map<Integer,Integer> proxy_map=club_proxy_tree.get(club_id);
		if(proxy_map==null) {
			proxy_map=new HashMap<>();
			proxy_map.put(uid, father_uid);
			club_proxy_tree.put(club_id, proxy_map);
		}else {
			List<Integer> oldParents=getParentIds(club_id, uid);
			//更新关系
			proxy_map.put(uid, father_uid);
			List<Integer> newParents=getParentIds(club_id, uid);
			Set<Integer> set=new HashSet<>();
			set.addAll(oldParents);
			set.addAll(newParents);
		}
		//开始移除缓存
		redisUtil.del(RedisConsts.HOT_EXTENSION+"_"+club_id);
		System.out.println("俱乐部:"+club_id+"关系树:"+club_proxy_tree.get(club_id));
	}


	public void proxyRebindDynamic(Integer club_id, Integer uid, Integer father_uid) {
		System.out.println("俱乐部:"+club_id+",用户:"+uid+"下面的所有直属下级重新绑定到上级为:"+father_uid);
		Map<Integer,Integer> proxy_map=club_proxy_tree.get(club_id);
		if(proxy_map==null) {
			proxy_map=new HashMap<>();
			club_proxy_tree.put(club_id, proxy_map);
		}else {
			List<Integer> zs=getZsSubIds(club_id, uid);
			System.out.println("该用户原来的直属下级有:"+zs);
			proxy_map.remove(uid);
			if(!zs.isEmpty()) {
				for(int zsuid:zs) {
					proxy_map.put(zsuid, father_uid);
				}
			}
		}
		//开始移除缓存
		redisUtil.del(RedisConsts.HOT_EXTENSION+"_"+club_id);
		redisUtil.del(RedisConsts.HOT_CLUBMEMBER_PROXY+"_"+club_id);
		System.out.println("俱乐部:"+club_id+"关系树:"+club_proxy_tree.get(club_id));		
	}
}
